package packets;

import java.util.HashMap;

import exceptions.UnrecoverableException;

import network.MCConnection;
import packets.c2spackets.*;
import world.WorldState;


/**
 * This class can dispatche messages to their corresponding handler.
 * 
 * For each type of packet, a handler object is created and ready for use.
 * The packet handlers have acces to dispatch commands to a minecraft world.
 * To get this world (and to avoid publics / singletons) each handler has to
 * know the world as a paramater.
 * 
 * A hashmap is used to quicly find the world-objects. A hashset is quick
 * in this context because we are comparing integers as hash-keys.
 * 
 */
public class Dispatcher {

	private HashMap<Integer, PacketHandler> packetmap;
	
	
	public Dispatcher(WorldState world) {
		System.out.println("Initialize Packet Dispatcher");
		packetmap = new HashMap<Integer, PacketHandler>();
		
		packetmap.put(-1, new P0xFF0(world));
		
		packetmap.put(0x00, new P0x00(world));
		packetmap.put(0x01, new P0x01(world));
		packetmap.put(0x02, new P0x02(world));
		packetmap.put(0x03, new P0x03(world));
		
		packetmap.put(0x10, new P0x10(world));

		packetmap.put(0x0A, new P0x0A(world));
		packetmap.put(0x0B, new P0x0B(world));
		packetmap.put(0x0C, new P0x0C(world));
		packetmap.put(0x0D, new P0x0D(world));
		
		packetmap.put(0x12, new P0x12(world));
		packetmap.put(0x13, new P0x13(world));
		
		packetmap.put(0x65, new P0x65(world));
		packetmap.put(0x6B, new P0x6B(world));

		
		packetmap.put(0xFE, new P0xFE(world));
		packetmap.put(0xFF, new P0xFF(world));

	}
	
	
	/**
	 * Dispatch a expected packet to a correct handler class.
	 * The message is assumed to be still on the sockets input buffer.
	 * The message-code is assumed to be removed from the input buffer
	 *  (and to be used as a method parameter). 
	 * 
	 * @param messagecode The message code.
	 * @param conn
	 */
	public void dispatch(Integer messagecode, MCConnection conn) {	
		try {
			packetmap.get(messagecode).handle(conn);
			
		} catch (NullPointerException e) {
			
			if(!packetmap.containsKey(messagecode)) {
				System.out.println("An unimplemented message was received from the client.");
				System.out.println(" The message-code is: "+messagecode);
				System.out.println(" The server can not continue parsing the input stream,");
				System.out.println(" and thus the connection is being closed!");
				
				conn.disconnect("Woops. The server does not know how to handle that action! Sorry :(");
			} else {
				e.printStackTrace();
			}
			conn.disconnect();
		} catch (UnrecoverableException e) {
			//an unrecoverable exceptions was caught:
			// disconnect the user!
			conn.disconnect();
		}
	}
}



